package com.itheima.search.util;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.Refresh;
import co.elastic.clients.elasticsearch._types.Result;
import co.elastic.clients.elasticsearch.core.DeleteByQueryRequest;
import co.elastic.clients.elasticsearch.core.DeleteByQueryResponse;
import co.elastic.clients.elasticsearch.core.DeleteRequest;
import co.elastic.clients.elasticsearch.core.DeleteResponse;
import co.elastic.clients.elasticsearch.core.IndexRequest;
import co.elastic.clients.elasticsearch.core.IndexResponse;
import co.elastic.clients.elasticsearch.indices.DeleteIndexRequest;
import co.elastic.clients.elasticsearch.indices.DeleteIndexResponse;
import co.elastic.clients.elasticsearch.indices.ExistsRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.IOException;

/**
 * ES文档清空服务
 * 提供多种清空ES索引中文档的方式
 * @author NicelYHHello
 */
@Service
@Slf4j
public class EsClearService {

    private final ElasticsearchClient elasticsearchClient;

    public EsClearService(ElasticsearchClient elasticsearchClient) {
        this.elasticsearchClient = elasticsearchClient;
    }

    /**
     * 删除整个索引（包括所有文档和索引结构）
     * 注意：这会删除索引及其映射，需要谨慎使用
     * @param indexName 索引名称
     * @return 是否删除成功
     */
    public boolean deleteIndex(String indexName) {
        try {
            // 检查索引是否存在
            boolean exists = elasticsearchClient.indices()
                    .exists(ExistsRequest.of(e -> e.index(indexName)))
                    .value();
            
            if (!exists) {
                log.warn("索引 {} 不存在，无需删除", indexName);
                return true;
            }
            
            // 删除索引
            DeleteIndexResponse response = elasticsearchClient.indices()
                    .delete(DeleteIndexRequest.of(d -> d.index(indexName)));
            
            boolean acknowledged = response.acknowledged();
            if (acknowledged) {
                log.info("索引 {} 删除成功", indexName);
            } else {
                log.error("索引 {} 删除失败", indexName);
            }
            
            return acknowledged;
        } catch (IOException e) {
            log.error("删除索引 {} 时发生异常: {}", indexName, e.getMessage(), e);
            return false;
        }
    }

    /**
     * 使用delete-by-query删除索引中的所有文档（保留索引结构）
     * @param indexName 索引名称
     * @return 删除的文档数量
     */
    public long deleteAllDocuments(String indexName) {
        try {
            // 检查索引是否存在
            boolean exists = elasticsearchClient.indices()
                    .exists(ExistsRequest.of(e -> e.index(indexName)))
                    .value();
            
            if (!exists) {
                log.warn("索引 {} 不存在，无需删除文档", indexName);
                return 0;
            }
            
            // 使用delete-by-query删除所有文档
            DeleteByQueryRequest request = DeleteByQueryRequest.of(d -> d
                    .index(indexName)
                    .query(q -> q.matchAll(m -> m))
                    .refresh(true) // 立即刷新使删除操作立即可见
            );
            
            DeleteByQueryResponse response = elasticsearchClient.deleteByQuery(request);
            long deleted = response.deleted();
            
            log.info("索引 {} 中的 {} 个文档已删除", indexName, deleted);
            return deleted;
        } catch (IOException e) {
            log.error("删除索引 {} 中的文档时发生异常: {}", indexName, e.getMessage(), e);
            return -1;
        }
    }

    /**
     * 根据条件删除文档
     * @param indexName 索引名称
     * @param field 字段名
     * @param value 字段值
     * @return 删除的文档数量
     */
    public long deleteDocumentsByCondition(String indexName, String field, Object value) {
        try {
            // 检查索引是否存在
            boolean exists = elasticsearchClient.indices()
                    .exists(ExistsRequest.of(e -> e.index(indexName)))
                    .value();
            
            if (!exists) {
                log.warn("索引 {} 不存在，无需删除文档", indexName);
                return 0;
            }
            
            // 使用delete-by-query根据条件删除文档
            DeleteByQueryRequest request = DeleteByQueryRequest.of(d -> d
                    .index(indexName)
                    .query(q -> q.term(t -> t.field(field).value(v -> v.stringValue(value.toString()))))
                    .refresh(true) // 立即刷新使删除操作立即可见
            );
            
            DeleteByQueryResponse response = elasticsearchClient.deleteByQuery(request);
            long deleted = response.deleted();
            
            log.info("索引 {} 中满足条件 {}={} 的 {} 个文档已删除", indexName, field, value, deleted);
            return deleted;
        } catch (IOException e) {
            log.error("根据条件删除索引 {} 中的文档时发生异常: {}", indexName, e.getMessage(), e);
            return -1;
        }
    }

    /**
     * 删除指定ID的文档
     * @param indexName 索引名称
     * @param documentId 文档ID
     * @return 是否删除成功
     */
    public boolean deleteDocumentById(String indexName, String documentId) {
        try {
            // 检查索引是否存在
            boolean exists = elasticsearchClient.indices()
                    .exists(ExistsRequest.of(e -> e.index(indexName)))
                    .value();
            
            if (!exists) {
                log.warn("索引 {} 不存在，无法删除文档 {}", indexName, documentId);
                return false;
            }
            
            // 删除指定ID的文档
            DeleteRequest request = DeleteRequest.of(d -> d
                    .index(indexName)
                    .id(documentId)
                    .refresh(Refresh.True) // 立即刷新使删除操作立即可见
            );
            
            DeleteResponse response = elasticsearchClient.delete(request);
            Result result = response.result();
            
            if (result == Result.Deleted) {
                log.info("文档 {} 从索引 {} 中删除成功", documentId, indexName);
                return true;
            } else if (result == Result.NotFound) {
                log.warn("文档 {} 在索引 {} 中不存在", documentId, indexName);
                return false;
            } else {
                log.error("文档 {} 从索引 {} 中删除失败，结果: {}", documentId, indexName, result);
                return false;
            }
        } catch (IOException e) {
            log.error("删除文档 {} 时发生异常: {}", documentId, e.getMessage(), e);
            return false;
        }
    }

    /**
     * 清空索引并重新创建（保留索引结构）
     * 先删除所有文档，然后可选地重新创建索引
     * @param indexName 索引名称
     * @param recreateIndex 是否重新创建索引
     * @return 是否成功
     */
    public boolean clearAndRecreateIndex(String indexName, boolean recreateIndex) {
        try {
            // 检查索引是否存在
            boolean exists = elasticsearchClient.indices()
                    .exists(ExistsRequest.of(e -> e.index(indexName)))
                    .value();
            
            if (!exists) {
                log.warn("索引 {} 不存在，无需清空", indexName);
                return true;
            }
            
            if (recreateIndex) {
                // 删除并重新创建索引
                deleteIndex(indexName);
                // 这里需要重新创建索引，可以使用ensureIndexExists方法
                // 由于索引创建逻辑较复杂，建议在实际使用时根据具体情况实现
                log.info("索引 {} 已删除，需要手动重新创建", indexName);
                return true;
            } else {
                // 只删除文档，保留索引结构
                long deleted = deleteAllDocuments(indexName);
                return deleted >= 0;
            }
        } catch (IOException e) {
            log.error("清空索引 {} 时发生异常: {}", indexName, e.getMessage(), e);
            return false;
        }
    }
}